home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / CDividedPane 1.0 / CDividedPane.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  6.8 KB  |  338 lines  |  [TEXT/KAHL]

  1. /*
  2.  *    File:        CDividedPane.c
  3.  *    Module:        CDividedPane method definitions
  4.  *    System:        Mark's Class Library
  5.  *    Evironment:    MacOS 7.0/THINK C 5.0/TCL 1.1.1
  6.  *    Author:        Mark Alldritt
  7.  *
  8.  *
  9.  *        Copyright © 1992  All Rights Reserved
  10.  *        Mark Alldritt
  11.  *        1571 Deep Cove Road
  12.  *        N. Vancouver, B.C. CANADA
  13.  *
  14.  *    
  15.  *    Description:
  16.  *
  17.  *    This class implements a pane that is divided either vertically or horizontally.  The
  18.  *    presentation is similar to that found in Microsoft Word or Microsoft Excel.
  19.  *
  20.  *
  21.  *    Edit History:
  22.  *
  23.  *    V01-01    Mark Alldritt    15-Jun-1992
  24.  *    - Initial version of module.
  25.  *
  26.  */
  27.  
  28.  
  29. extern RgnHandle    gUtilRgn;
  30.  
  31. #include "CDividedPane.h"
  32.  
  33.  
  34. #define V_DIVIDER_CURSOR_ID        10000
  35. #define H_DIVIDER_CURSOR_ID        10001
  36.  
  37.  
  38. static CursHandle    hDividerCursor = NULL,
  39.                     vDividerCursor = NULL;
  40.  
  41.  
  42. void CDividedPane::IDividedPane(CView *anEnclosure, CBureaucrat *aSupervisor,
  43.                                 short aWidth, short aHeight,
  44.                                 short aHEncl, short aVEncl,
  45.                                 SizingOption aHSizing, SizingOption aVSizing,
  46.                                 Boolean splitHorizontally,
  47.                                 short dividerPos, short dividerSize,
  48.                                 short min1st, short min2nd)
  49.  
  50. /*    Override:    no
  51.  *
  52.  *    Initialize this instance of CDividedPane.
  53.  */
  54.  
  55. {
  56.     inherited::IPane(anEnclosure, aSupervisor, aWidth, aHeight,
  57.                      aHEncl, aVEncl, aHSizing, aVSizing);
  58.     wantsClicks = TRUE;
  59.     visible = TRUE;
  60.     active = TRUE;
  61.  
  62.     /*    Set instance variables    */
  63.  
  64.     this->min1st = min1st;
  65.     this->min2nd = min2nd;
  66.     this->splitHorizontally = splitHorizontally;
  67.     this->dividerPos = dividerPos;
  68.     this->dividerSize = dividerSize;
  69.  
  70.     /*    Build sub-panes    */
  71.  
  72.     its1stPane = new(CPane);
  73.     its2ndPane = new(CPane);
  74.     
  75.     if (splitHorizontally)
  76.     {
  77.         its1stPane->IPane(this, this,
  78.                           frame.right + 1, dividerPos + 2, -1, -1,
  79.                           sizELASTIC, sizFIXEDTOP);
  80.         its2ndPane->IPane(this, this,
  81.                           frame.right + 1, frame.bottom - dividerPos - dividerSize + 1,
  82.                           -1, dividerPos + dividerSize - 1,
  83.                           sizELASTIC, sizELASTIC);
  84.     }
  85.     else
  86.     {
  87.         its1stPane->IPane(this, this,
  88.                           dividerPos + 2, frame.bottom + 1, -1, -1,
  89.                           sizFIXEDLEFT, sizELASTIC);
  90.         its2ndPane->IPane(this, this,
  91.                           frame.right - dividerPos - dividerSize + 1, frame.bottom + 1, 
  92.                           dividerPos + dividerSize - 1, -1,
  93.                           sizELASTIC, sizELASTIC);
  94.     }
  95.     its1stPane->wantsClicks = its2ndPane->wantsClicks = TRUE;
  96.  
  97.     /*    Load cursor resources as required    */
  98.  
  99.     if (splitHorizontally)
  100.     {
  101.         if (!vDividerCursor)
  102.             FailNILRes(vDividerCursor = GetCursor(V_DIVIDER_CURSOR_ID));
  103.     }
  104.     else
  105.         if (!hDividerCursor)
  106.             FailNILRes(hDividerCursor = GetCursor(H_DIVIDER_CURSOR_ID));
  107. }
  108.  
  109.  
  110. void CDividedPane::Draw(Rect *area)
  111.  
  112. /*    Override:    yes
  113.  *
  114.  *    Draw the divider.
  115.  */
  116.  
  117. {
  118.     Rect        r;
  119.  
  120.     LongToQDRect(&frame, &r);
  121.     if (splitHorizontally)
  122.     {
  123.         r.top = dividerPos;
  124.         r.bottom = r.top + dividerSize;
  125.         r.left--;
  126.         r.right++;
  127.     }
  128.     else
  129.     {
  130.         r.left = dividerPos;
  131.         r.right = r.left + dividerSize;
  132.         r.top--;
  133.         r.bottom++;
  134.     }
  135.  
  136.     PenPat(black);
  137.     FrameRect(&r);
  138. }
  139.  
  140.  
  141. void CDividedPane::DoClick(Point hitPt, short modifierKeys, long when)
  142.  
  143. /*    Override:    yes
  144.  *
  145.  *    Handle a mouse click.  If the user has clicked within the divider then we allow the
  146.  *    user to move the divider around.  When the mouse is released, resize the sub-panes
  147.  *    as appripriate and redraw everything.
  148.  */
  149.  
  150. {
  151.     Rect        r;
  152.  
  153.     LongToQDRect(&frame, &r);
  154.     if (splitHorizontally)
  155.     {
  156.         r.top = dividerPos;
  157.         r.bottom = r.top + dividerSize;
  158.         r.left--;
  159.         r.right++;
  160.     }
  161.     else
  162.     {
  163.         r.left = dividerPos;
  164.         r.right = r.left + dividerSize;
  165.         r.top--;
  166.         r.bottom++;
  167.     }
  168.  
  169.     if (PtInRect(hitPt, &r))
  170.     {
  171.         long    result;
  172.         Rect    frameR;
  173.         Rect    slopR;
  174.         
  175.         RectRgn(gUtilRgn, &r);
  176.         LongToQDRect(&frame, &frameR);
  177.         slopR = frameR;
  178.         if (splitHorizontally)
  179.         {
  180.             frameR.top += min1st;
  181.             frameR.bottom -= min2nd;
  182.         }
  183.         else
  184.         {
  185.             frameR.left += min1st;
  186.             frameR.right -= min2nd;
  187.         }
  188.         result = DragGrayRgn(gUtilRgn, hitPt, &frameR, &slopR, 
  189.                              splitHorizontally ? vAxisOnly : hAxisOnly, NULL);
  190.  
  191.         if (result != 0x80008000)
  192.         {
  193.             Rect    delta1st,
  194.                     delta2nd;
  195.  
  196.             InvalRect(&r);
  197.             if (splitHorizontally)
  198.             {
  199.                 if (HiWord(result) == 0)
  200.                     return;
  201.                 dividerPos += HiWord(result);
  202.                 r.top += HiWord(result);
  203.                 r.bottom += HiWord(result);
  204.  
  205.                 /*    Build delta rectangles for the following ChangeSize calls.    */
  206.  
  207.                 delta1st.top = delta1st.left = delta1st.right = 0;
  208.                 delta1st.bottom = HiWord(result);
  209.                 delta2nd.left = delta2nd.right = delta2nd.top = 0;
  210.                 delta2nd.bottom = -HiWord(result);
  211.             }
  212.             else
  213.             {
  214.                 if (LoWord(result) == 0)
  215.                     return;
  216.                 dividerPos += LoWord(result);
  217.                 r.left += LoWord(result);
  218.                 r.right += LoWord(result);
  219.  
  220.                 /*    Build delta rectangles for the following ChangeSize calls.    */
  221.  
  222.                 delta1st.top = delta1st.left = delta1st.bottom = 0;
  223.                 delta1st.right = LoWord(result);
  224.                 delta2nd.top = delta2nd.left = delta2nd.bottom = 0;
  225.                 delta2nd.right = -LoWord(result);
  226.             }
  227.  
  228.             its1stPane->ChangeSize(&delta1st, its1stPane->autoRefresh);
  229.             if (splitHorizontally)
  230.                 its2ndPane->Offset(0, HiWord(result), FALSE);
  231.             else
  232.                 its2ndPane->Offset(LoWord(result), 0, FALSE);
  233.             its2ndPane->ChangeSize(&delta2nd, its2ndPane->autoRefresh);
  234.             Refresh();
  235.         }
  236.     }
  237. }
  238.  
  239.  
  240. void CDividedPane::AdjustCursor(Point where, RgnHandle mouseRgn)
  241.  
  242. /*    Override:    yes
  243.  *
  244.  *    Whenever the mouse passes over the divider change the cursor to an up/down arrow or
  245.  *    a left/arrow, depending on the type of pane division.
  246.  */
  247.  
  248. {
  249.     Rect        dividerR,
  250.                 r;
  251.     Rect        aperture;
  252.     LongRect    lr;
  253.     LongPt        lp;
  254.     Point        mousePos;
  255.     
  256.     mousePos = where;
  257.     WindToFrame(mousePos, &lp);
  258.     LongToQDPt(&lp, &mousePos);
  259.  
  260.     LongToQDRect(&frame, &aperture);
  261.     LongToQDRect(&frame, ÷rR);
  262.     if (splitHorizontally)
  263.     {
  264.         dividerR.top = dividerPos;
  265.         dividerR.bottom = dividerR.top + dividerSize;
  266.         dividerR.left--;
  267.         dividerR.right++;
  268.     }
  269.     else
  270.     {
  271.         dividerR.left = dividerPos;
  272.         dividerR.right = dividerR.left + dividerSize;
  273.         dividerR.top--;
  274.         dividerR.bottom++;
  275.     }
  276.  
  277.     if (PtInRect(mousePos, ÷rR))
  278.     {
  279.         SetCursor(splitHorizontally ? *vDividerCursor : *hDividerCursor);
  280.     
  281.         RectRgn(gUtilRgn, ÷rR);
  282.         FrameToGlobalR(&frame, &r);
  283.         OffsetRgn(gUtilRgn, dividerR.left - r.left, dividerR.top - r.top);    
  284.         SectRgn(mouseRgn, gUtilRgn, mouseRgn);
  285.     }
  286.     else
  287.     {
  288.         RgnHandle    dividerRgn;
  289.  
  290.         inherited::AdjustCursor(where, mouseRgn);
  291.  
  292.         dividerRgn = NewRgn();
  293.         RectRgn(dividerRgn, ÷rR);
  294.         RectRgn(gUtilRgn, &aperture);
  295.         DiffRgn(gUtilRgn, dividerRgn, gUtilRgn);
  296.         DisposeRgn(dividerRgn);
  297.  
  298.         FrameToGlobalR(&lr, &r);
  299.         OffsetRgn(gUtilRgn, aperture.left - r.left, aperture.top - r.top);
  300.         SectRgn(mouseRgn, gUtilRgn, mouseRgn);
  301.     }
  302. }
  303.  
  304.  
  305. short CDividedPane::GetDividerPos()
  306.  
  307. /*    Override:    no
  308.  *
  309.  *    Return the current position of the divider.
  310.  */
  311.  
  312. {
  313.     return (dividerPos);
  314. }
  315.  
  316.  
  317. CPane *CDividedPane::Get1stPane()
  318.  
  319. /*    Override:    no
  320.  *
  321.  *    Return the handle of the top or left pane within the divided pane.
  322.  */
  323.  
  324. {
  325.     return (its1stPane);
  326. }
  327.  
  328.  
  329. CPane *CDividedPane::Get2ndPane()
  330.  
  331. /*    Override:    no
  332.  *
  333.  *    Return the handle of the bottom or right pane within the divided pane.
  334.  */
  335.  
  336. {
  337.     return (its2ndPane);
  338. }